#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import os
import re
import socket
from functools import wraps

from common.common import get_local_ips
from common.exception.common_exception import ErrCodeException
from common.logger import Logger
from generaldb.saphana.comm.saphana_const import SaphanaErrorCode

log = Logger().get_logger("saphana.log")


def get_value_from_str_lines(str_lines: str, point_key: str, no_contain_str, is_start=False):
    """
    从字符串中循环根据每行的内容，找到第一个匹配目标字符串的行，返回此行中的其它字符串
    :param str_lines: 目标字符串
    :param point_key: 目标关键字
    :param no_contain_str: 不能包含此字符串
    :param is_start: 是否以目标关键字开头
    :return: 匹配行中的其它字符串
    """
    point_key = point_key.replace(" ", "")
    lines = str_lines.splitlines()
    for line in lines:
        line = line.replace(" ", "")
        match_obj = re.search(point_key, line, re.IGNORECASE)
        if match_obj:
            if no_contain_str != "" and re.search(no_contain_str, line, re.IGNORECASE) is not None:
                continue
            if is_start and not line.startswith(point_key):
                continue
            return re.sub(point_key, '', line, flags=re.IGNORECASE).strip()
    return ""


def get_value_from_str_lines_with_filter(str_lines: str, point_key: str, no_contain_str_arr: list):
    """
    从字符串中循环根据每行的内容，找到第一个匹配目标字符串的行，返回此行中的其它字符串
    :param str_lines: 目标字符串
    :param point_key: 目标关键字
    :param no_contain_str_arr: 不能包含数组里的任意字符串
    :return: 匹配行中的其它字符串
    """
    lines = str_lines.splitlines()
    for line in lines:
        match_obj = re.search(point_key, line, re.IGNORECASE)
        if match_obj is None:
            continue
        # 如果没有不能包含的字符串，则直接return
        if no_contain_str_arr is None:
            return re.sub(point_key, '', line, flags=re.IGNORECASE).strip()
        is_true = True
        for no_contain_str in no_contain_str_arr:
            # 如果包含有不能有的字符串，则忽略掉，继续匹配
            if re.search(no_contain_str, line, re.IGNORECASE) is not None:
                is_true = False
                continue
        if is_true:
            return re.sub(point_key, '', line, flags=re.IGNORECASE).strip()
    return ""


def get_agent_ips_str(agent_ip_list: list):
    agent_ips_str = ""
    for agent_ips in agent_ip_list:
        agent_ip_arr = agent_ips.split(",")
        if not agent_ip_arr:
            continue
        if not agent_ip_arr[0]:
            continue
        agent_ips_str += agent_ip_arr[0] + ","
    return agent_ips_str[:-1]


def get_db_distributed_nodes_str(db_distributed_nodes: list, hostname_file_content: str):
    db_distributed_nodes_str = ""
    for node_hostname in db_distributed_nodes:
        node_ip = get_value_from_str_lines_with_filter(str(hostname_file_content), node_hostname,
                                                       ["#", "ipv6-localhost", "ipv6-loopback",
                                                        "ipv4-localhost", "ipv4-loopback", "127.0.0.1"])
        if not node_ip:
            node_ip = node_hostname
        db_distributed_nodes_str += node_ip + ","
    return db_distributed_nodes_str[:-1]


def get_localhost_hostname():
    ips = get_local_ips()
    hostname_file_content = get_hostnames_in_env()
    for local_ip in ips:
        local_hostname = get_value_from_str_lines(str(hostname_file_content), local_ip, "#")
        if local_hostname:
            log.debug(f"Local ip: {local_ip}, hostname: {local_hostname}")
            return local_hostname
    raise ErrCodeException(SaphanaErrorCode.DB_ENV_ERROR, message="Get localhost name error.")


def get_localhost_register_ip(all_register_nodes: list):
    # 获取本机注册到PM的IP地址
    ips = get_local_ips()
    for each_ip in ips:
        if each_ip in all_register_nodes:
            log.debug(f"Register ip: {each_ip}.")
            return each_ip
    return socket.gethostname()


def get_hostnames_in_env():
    """
    获取/etc/hosts文件内容
    :return:
    """
    hostname_file_path = "/etc/hosts"
    if not os.path.exists(hostname_file_path):
        raise ErrCodeException(SaphanaErrorCode.DB_ENV_ERROR,
                               message="Saphana cluster no hosts file.")
    with open(hostname_file_path, 'r', encoding='utf-8') as file_read:
        return file_read.read()


def log_start():
    """
    功能描述： 函数开始-结束添加日志打印
    """

    def decorator(fun_name):
        @wraps(fun_name)
        def inner(*args, **kwargs):
            log.info(f"Enter {fun_name.__name__}")
            ret = fun_name(*args, **kwargs)
            log.info(f"End with [{ret}], {fun_name.__name__}")
            return ret

        return inner

    return decorator
